﻿using Fleck;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Newtonsoft.Json.Linq;
using System.Threading;
using Chess.Models;
using System.Web.Security;
using System.Web.Script.Serialization;
using System.Net.Http;
using System.Net.Http.Headers;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;

namespace Chess
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public enum MessageType
        {
            Register,   //0
            Chat,       //1
            Server,     //2       
            Broadcast,  //3          
            Leave,      //4
            SendListFriend, //5
            Logout,         //6
            Online,         //7
            Offline,        //8
            AddFriend,      //9
            ResultAddFriend,//10
            CancelFriend,   //11
            ClientGoIntoRoom,//12
            ClientGoOutOfRoom,//13
            UpdateStatusOfRoom,//14
            UpdateUser01,//15
            UpdateUser02,//16
            StartGame, //17
            ChatInGame, //18
            DanhCo, //19
            Win,//20
            KickPlayer,//21
            CreateRoom,//22
            CancelRoom, //23
            InviteFriend,//24
            InviteRequest,//25
            GoToRoom//26
        } 

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "KiemTraTaiKhoan", // Route name
                "Account/KiemTraTaiKhoan/{TenDangNhap}", // URL with parameters
                new { controller = "Account", action = "KiemTraTaiKhoan" }); // Parameter defaults

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Account", action = "DangNhap", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            // Use LocalDB for Entity Framework by default
            Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
            thread.Start();

            //Start websocket server
            //WebsocketWs wsocket = new WebsocketWs();
            //Thread t = new Thread(new ThreadStart(wsocket.startWebsocket));
            //t.Start();
        }

        public static List<UserModel> _Users = new List<UserModel>();

        protected void Session_End(object sender, EventArgs e)
        {
            if (Session["TaiKhoan"] != null)
            {
                FormsAuthentication.SignOut();
                Session["TaiKhoan"] = null;
            }
        }

        protected void Session_Start(object sender, EventArgs e)
        {
            Session["TaiKhoan"] = null;
        }

        public void WorkThreadFunction()
        {
            try
            {
                FleckLog.Level = LogLevel.Debug;
                List<UserInfo> listUserOnline = new List<UserInfo>();
                int nPhong = 12;
                List<Phong> listPhong = new List<Phong>();
                for (int i = 0; i < nPhong; i++)
                {
                    Phong phong=new Phong();
                    phong.IdPhong=i;
                    listPhong.Add(phong);
                }

                var server = new WebSocketServer("ws://localhost:8181");

                server.Start(socket =>
                {
                    socket.OnOpen = () =>
                    {
                        UserInfo UserInfo = new Models.UserInfo();
                        UserInfo.Socket = socket;
                        listUserOnline.Add(UserInfo);

                    };
                    socket.OnClose = () =>
                    {
                    };
                    socket.OnMessage = message =>
                    {
                        var ser = new JavaScriptSerializer();
                        Message msg = ser.Deserialize<Message>(message);

                        switch (msg.Type)
                        {
                            case MessageType.Register: // 0 : Đăng ký
                                {
                                    XuLyDangKy(listUserOnline, socket, ser, msg,listPhong);
                                    break;
                                }
                            case MessageType.Chat:  // 1: Chat
                                {
                                    foreach (UserInfo item in listUserOnline)
                                    {
                                        if (item.IdTaiKhoan == msg.ToID)
                                        {
                                            item.Socket.Send(ser.Serialize(msg));
                                            break;
                                        }
                                    }
                                    break;
                                }
                            case MessageType.Server: // 2: Server
                                {
                                    //Xử lý khi client logout, cập nhật danh sách cách thành viên còn lại.
                                    break;
                                }
                            case MessageType.Offline: //8
                                {
                                    XuLyOffLine(listUserOnline, ser, msg);
                                    break;
                                }
                            case MessageType.AddFriend:
                                {
                                    XuLyThemBan(listUserOnline, socket, ser, msg);
                                    break;
                                }
                            case MessageType.CancelFriend:
                                {
                                    XuLyHuyBan(listUserOnline, socket, ser, msg);
                                    break;
                                }
                            case MessageType.ClientGoIntoRoom:
                                {
                                    XuLyClientGoIntoRoom(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.StartGame:
                                {
                                    XuLyStartGame(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.ChatInGame:
                                {
                                    XuLyChatTrongGame(listUserOnline,socket,ser,msg,listPhong);
                                    break;
                                }
                            case MessageType.DanhCo:
                                {
                                    XuLuDanhCo(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.ClientGoOutOfRoom:
                                {
                                    XuLyClientGoOutOfRoom(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.Win:
                                { 
                                    XuLyWin(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.KickPlayer:
                                {
                                    XuLyKickPlayer(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.CreateRoom:
                                {
                                    XuLyCreateRoom(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.CancelRoom:
                                {
                                    XuLyCancelRoom(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.InviteFriend:
                                {
                                    XuLyInviteFriend(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                            case MessageType.InviteRequest:
                                {
                                    XuLyInviteRequest(listUserOnline, socket, ser, msg, listPhong);
                                    break;
                                }
                        }
                    };
                });
            }
            catch (Exception ex)
            {
                int a = 2;
            }
        }

        private void XuLyInviteRequest(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + msg.ToUser).Result;
            TaiKhoan ToAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
            foreach (UserInfo item in listUserOnline)
            {
                if (item.IdTaiKhoan == ToAcc.Id)
                {
                    if (item.UserStatus == USER_STATUS.FREE) {
                        response = client.GetAsync("api/TaiKhoan/" + msg.UserName).Result;
                        TaiKhoan FromAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                        item.Socket.Send(ser.Serialize(new
                        {
                            Type = MessageType.InviteFriend,
                            Result = msg.Result,
                            fromUser = msg.UserName
                        }));
                        int roomID = addNewRoom(listPhong, listUserOnline, ser);
                        make2PlayerGoToThisRoom(msg.Id, ToAcc.Id, roomID, listUserOnline, ser);
                    }
                    break;
                }
            }
        }

        private int addNewRoom(List<Phong> listPhong, List<UserInfo> listUserOnline, JavaScriptSerializer ser)
        {
            int nPhong = listPhong.Count;
            Phong phong = new Phong();
            phong.IdPhong = nPhong;
            listPhong.Add(phong);
            foreach (UserInfo item in listUserOnline)
            {
                item.Socket.Send(ser.Serialize(new
                {
                    Type = MessageType.CreateRoom,
                    Result = true,
                    IdPhong = phong.IdPhong,
                    SoNguoi = 0
                }));
            }
            return phong.IdPhong;
        }

        private void make2PlayerGoToThisRoom(int id1, int id2, int roomID, List<UserInfo> listUser, JavaScriptSerializer ser)
        {
            UserInfo user1 = GetUserInfo(id1, listUser);
            UserInfo user2 = GetUserInfo(id2, listUser);
            user1.Socket.Send(ser.Serialize(new
            {
                Type = MessageType.GoToRoom,
                idPhong = roomID,
                SoNguoi = 0
            }));
            user2.Socket.Send(ser.Serialize(new
            {
                Type = MessageType.GoToRoom,
                idPhong = roomID,
                SoNguoi = 1
            }));
        }

        private void XuLyInviteFriend(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + msg.ToUser).Result;
            TaiKhoan ToAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
            if (ToAcc != null)
            {
                foreach (UserInfo item in listUserOnline)
                {
                    if (item.IdTaiKhoan == ToAcc.Id)
                    {
                        response = client.GetAsync("api/TaiKhoan/" + msg.UserName).Result;
                        TaiKhoan FromAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                        item.Socket.Send(ser.Serialize(new
                        {
                            Type = MessageType.InviteRequest,
                            Result = true,
                            fromUser = msg.UserName
                        }));
                        break;
                    }
                }
            }
            else
            {
                socket.Send(ser.Serialize(new
                {
                    Type = MessageType.CancelFriend,
                    Result = false
                }));
            }
        }

        private void XuLyCancelRoom(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int idPhong = msg.IdPhong;
            int id = msg.Id;
            int index = -1;
            for (int i = 0; i < listPhong.Count; i++)
            {
                if (listPhong[i].IdPhong == idPhong)
                {
                    if (listPhong[i].SoNguoi == 2) {
                        if (listPhong[i].IdNguoiChoiMot == id)
                        {
                            listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                            {
                                Type = MessageType.CancelRoom,
                                Result = true,
                                IdPhong = idPhong,
                                SoNguoi = 0
                            }));
                        }
                        else if (listPhong[i].IdNguoiChoiHai == id)
                        {
                            listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                            {
                                Type = MessageType.CancelRoom,
                                Result = true,
                                IdPhong = idPhong,
                                SoNguoi = 0
                            }));
                        }
                    }
                    index = i;
                    listPhong[i].SoNguoi = 0;
                    listPhong[i].IdNguoiChoiMot = -1;
                    listPhong[i].IdNguoiChoiHai = -1;
                    listPhong[i].SocketNguoiChoi1 = null;
                    listPhong[i].SocketNguoiChoi2 = null;
                    break;
                }
            }

            UpdateRoomStatus(listUserOnline, ser, listPhong, idPhong, index);
        }

        private void XuLyCreateRoom(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int idPhong = msg.IdPhong;
            int id = msg.Id;
            Phong phong = new Phong();
            phong.IdPhong = idPhong;
            phong.SoNguoi = 0;
            listPhong.Add(phong);
            foreach (UserInfo item in listUserOnline)
            {
                item.Socket.Send(ser.Serialize(new
                {
                    Type = MessageType.CreateRoom,
                    Result = true,
                    IdPhong = idPhong,
                    SoNguoi = 0
                }));
            }
        }

        private void XuLyKickPlayer(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int idPhong = msg.IdPhong;
            int nPhong = listPhong.Count;
            int id = msg.Id;

            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == idPhong)
                {
                    if (listPhong[i].IdNguoiChoiMot == id)
                    {
                        listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                        {
                            Type = MessageType.KickPlayer,
                        }));
                        listPhong[i].SocketNguoiChoi2 = null;
                        listPhong[i].IdNguoiChoiHai = -1;
                    }
                    else if (listPhong[i].IdNguoiChoiHai == id)
                    {
                        listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                        {
                            Type = MessageType.KickPlayer,
                        }));
                        listPhong[i].SocketNguoiChoi1 = null;
                        listPhong[i].IdNguoiChoiMot = -1;
                    }
                    listPhong[i].SoNguoi--;
                    UpdateRoomStatus(listUserOnline, ser, listPhong, idPhong, i);
                    break;
                }
            }
        }

        private void XuLyWin(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int idPhong = msg.IdPhong;
            int nPhong = listPhong.Count;
            int id = msg.Id;

            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == idPhong)
                {
                    if (listPhong[i].IdNguoiChoiMot == id)
                    {
                        listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                        {
                            Type = MessageType.Win,
                            Result = true,
                        }));
                    }
                    else if (listPhong[i].IdNguoiChoiHai == id)
                    {
                        listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                        {
                            Type = MessageType.Win,
                        }));
                    }
                    break;
                }
            }
        }

        private void XuLyClientGoOutOfRoom(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int IDPhong = msg.IdPhong;
            int nPhong = listPhong.Count;
            int index = -1;
            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == IDPhong)
                {
                    listPhong[i].SoNguoi --;
                    index = i;
                    if (listPhong[i].IdNguoiChoiMot == msg.Id)
                    {
                        listPhong[i].IdNguoiChoiMot = -1;
                        listPhong[i].SocketNguoiChoi1 = null;
                        listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                        {
                            Type = MessageType.ClientGoOutOfRoom,
                        }));
                    }
                    else 
                    {
                        listPhong[i].IdNguoiChoiHai = -1;
                        listPhong[i].SocketNguoiChoi2 = null;
                        listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                        {
                            Type = MessageType.ClientGoOutOfRoom,
                        }));
                    }
                    if (listPhong[i].SoNguoi == 1) {//day sang vi tri dau
                        if (listPhong[i].IdNguoiChoiMot == -1) {
                            listPhong[i].IdNguoiChoiMot = listPhong[i].IdNguoiChoiHai;
                            listPhong[i].IdNguoiChoiHai = -1;
                            listPhong[i].SocketNguoiChoi1 = listPhong[i].SocketNguoiChoi2;
                            listPhong[i].SocketNguoiChoi2 = null;
                        }
                    }
                    break;
                }
            }
            setUserFree(listUserOnline, msg.Id);
            UpdateRoomStatus(listUserOnline, ser, listPhong, IDPhong, index);
        }

        private static void UpdateRoomStatus(List<UserInfo> listUserOnline, JavaScriptSerializer ser, List<Phong> listPhong, int IDPhong, int index)
        {
            foreach (UserInfo item in listUserOnline)
            {
                item.Socket.Send(ser.Serialize(new
                {
                    Type = MessageType.UpdateStatusOfRoom,
                    Result = true,
                    IdPhong = IDPhong,
                    SoNguoi = listPhong[index].SoNguoi
                }));
            }
        }

        private void XuLuDanhCo(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int fromCell = msg.FromCell;
            int toCell = msg.ToCell;
            int idPhong = msg.IdPhong;
            int nPhong = listPhong.Count;
            int id = msg.Id;

            int fromCell_C = TransformCellPosition(fromCell);
            int toCell_C = TransformCellPosition(toCell);

            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == idPhong)
                {
                    if (listPhong[i].IdNguoiChoiMot == id)
                    {
                        //Rui gui xuong cho thang ben kia, co chuyen doi gi khong
                        //
                        listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                        {
                            Type = MessageType.DanhCo,
                            Result = true,
                            FromCell =fromCell_C,
                            ToCell=toCell_C

                        }));
                    }
                    else if (listPhong[i].IdNguoiChoiHai == id)
                    {
                        listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                        {
                            Type = MessageType.DanhCo,
                            Result = true,
                            FromCell = fromCell_C,
                            ToCell = toCell_C
                        }));
                    }
                    break;
                }
            }
        }

        private void XuLyChatTrongGame(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int IdPhong = msg.IdPhong;
            int IdNguoiGui = msg.Id;
            int UsernameNguoiGui = msg.Id;
            int nPhong = listPhong.Count;
            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == IdPhong)
                {
                    if (listPhong[i].IdNguoiChoiMot == IdNguoiGui)
                    {
                        listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(msg));
                    }
                    else if (listPhong[i].IdNguoiChoiHai == IdNguoiGui)
                    {
                        listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(msg));
                    }
                    break;
                }
            }
        }

        private void XuLyStartGame(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int IdPhong = msg.IdPhong;
            int nPhong = listPhong.Count;
            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == IdPhong)
                {
                    //Gửi thông điệp bắt đầu trận đấu cho người chơi 1 là người đi trước.
                    listPhong[i].SocketNguoiChoi1.Send(ser.Serialize(new
                    {
                        Type = MessageType.StartGame,
                        Result = true,
                        ThuTuDi=1
                    }));  
                    //Gửi thông điệp bắt đầu trận đấu cho người chơi 2 là người đi sau.
                    listPhong[i].SocketNguoiChoi2.Send(ser.Serialize(new
                    {
                        Type = MessageType.StartGame,
                        Result = true,
                        ThuTuDi = 2
                    }));
                    break;
                }
            }
        }

        private void XuLyClientGoIntoRoom(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg, List<Phong> listPhong)
        {
            int IDPhong = msg.IdPhong;
            int SoNguoi = msg.SoNguoi;
            int nPhong=listPhong.Count;
            int index = -1;
            setUserNotFree(listUserOnline, msg.Id);
            for (int i = 0; i < nPhong; i++)
            {
                if (listPhong[i].IdPhong == IDPhong)
                {
                    listPhong[i].SoNguoi = SoNguoi;
                    index = i;
                    if (listPhong[i].IdNguoiChoiMot == -1) {
                        listPhong[i].IdNguoiChoiMot = msg.Id;
                        listPhong[i].SocketNguoiChoi1 = socket;
                    }
                    else if (listPhong[i].IdNguoiChoiHai == -1) {
                        listPhong[i].IdNguoiChoiHai = msg.Id;
                        listPhong[i].SocketNguoiChoi2 = socket;
                    }
                    //if (SoNguoi == 1)
                    //{
                    //    listPhong[i].IdNguoiChoiMot = msg.Id;
                    //    listPhong[i].SocketNguoiChoi1 = socket;
                    //}
                    //else if (SoNguoi == 2)
                    //{
                    //    listPhong[i].IdNguoiChoiHai = msg.Id;
                    //    listPhong[i].SocketNguoiChoi2 = socket;
                    //}                    
                    break;
                }
            }
            
            //Nếu sô người 1 thì đã xong
            foreach (UserInfo item in listUserOnline)
            {
                if (item.IdTaiKhoan != msg.Id)
                {
                    item.Socket.Send(ser.Serialize(new
                    {
                        Type = MessageType.UpdateStatusOfRoom,
                        Result = true,
                        IdPhong = IDPhong,
                        SoNguoi = SoNguoi
                    }));
                }
            }
                        
            if (SoNguoi == 2)
            {
                //Cập nhật cho người chơi 1.
                UserInfo user02 = GetUserInfo(listPhong[index].IdNguoiChoiHai, listUserOnline);
                listPhong[index].SocketNguoiChoi1.Send(ser.Serialize(new
                {
                    Type = MessageType.UpdateUser01,
                    Result = true,
                    UserName = user02.UserName,
                    Id = user02.IdTaiKhoan
                }));                
                //Cập nhật cho người chơi 2.
                UserInfo user01 = GetUserInfo(listPhong[index].IdNguoiChoiMot, listUserOnline);
                listPhong[index].SocketNguoiChoi2.Send(ser.Serialize(new
                {
                    Type = MessageType.UpdateUser02,
                    Result = true,
                    UserName = user01.UserName,
                    Id = user01.IdTaiKhoan
                }));  
            }            
        }

        private void setUserNotFree(List<UserInfo> listUserOnline, int id)
        {
            UserInfo user = GetUserInfo(id, listUserOnline);
            user.UserStatus = USER_STATUS.NOTFREE;
        }

        private void setUserFree(List<UserInfo> listUserOnline, int id)
        {
            UserInfo user = GetUserInfo(id, listUserOnline);
            user.UserStatus = USER_STATUS.FREE;
        }

        private UserInfo GetUserInfo(int IdUser, List<UserInfo> listUser)
        {
            int n=listUser.Count;
            for (int i = 0; i < n; i++)
            {
                if (listUser[i].IdTaiKhoan == IdUser)
                {
                    return listUser[i];
                    break;
                }
            }
            return null;
        }

        private static void XuLyHuyBan(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg)
        {
            //Kiem tra username co ton tai hay khong.
            //Kiem tra toan tai cua ToUser, neu co thi lay thong tin.
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + msg.ToUser).Result;
            TaiKhoan ToAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
            if (ToAcc != null)
            {
                foreach (UserInfo item in listUserOnline)
                {
                    if (item.IdTaiKhoan == ToAcc.Id)
                    {
                        response = client.GetAsync("api/TaiKhoan/" + msg.UserName).Result;
                        TaiKhoan FromAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                        item.Socket.Send(ser.Serialize(new
                        {
                            Type = MessageType.CancelFriend,
                            Result = true,
                            Id = FromAcc.Id
                        }));
                        break;
                    }
                }
                //Cập nhật danh sách bạn của người yêu cầu huy kết bạn.
                socket.Send(ser.Serialize(new
                {
                    Type = MessageType.CancelFriend,
                    Result = true,
                    Id = ToAcc.Id
                }));
                response = client.DeleteAsync("api/Friend/" + ToAcc.Id + "/" + msg.Id).Result;
            }
            else
            {
                socket.Send(ser.Serialize(new
                {
                    Type = MessageType.CancelFriend,
                    Result = false
                }));
            }
        }

        private static void XuLyOffLine(List<UserInfo> listUserOnline, JavaScriptSerializer ser, Message msg)
        {
            foreach (UserInfo item in listUserOnline)
            {
                List<TaiKhoan> dsBanBe = item.DanhSachBan;
                foreach (TaiKhoan itembb in dsBanBe)
                {
                    if (itembb.Id == msg.Id)
                    {
                        itembb.IsOnline = false;
                        item.Socket.Send(ser.Serialize(new
                        {
                            Type = MessageType.Offline,
                            Id = msg.Id
                        }));
                        break;
                    }
                }
            }

            foreach (UserInfo item in listUserOnline)
            {
                if (item.IdTaiKhoan == msg.Id)
                {
                    listUserOnline.Remove(item);
                    break;
                }
            }
        }

        private static void XuLyThemBan(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg)
        {
            //Kiem tra toan tai cua ToUser, neu co thi lay thong tin.
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + msg.ToUser).Result;
            TaiKhoan ToAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
            if (ToAcc != null)
            {
                bool IsOnline = false;
                foreach (UserInfo item in listUserOnline)
                {
                    if (item.IdTaiKhoan == ToAcc.Id)
                    {
                        IsOnline = true;
                        response = client.GetAsync("api/TaiKhoan/" + msg.UserName).Result;
                        TaiKhoan FromAcc = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                        IsOnline = true;
                        FromAcc.IsOnline = true;
                        item.Socket.Send(ser.Serialize(new
                        {
                            Type = MessageType.ResultAddFriend,
                            Result = true,
                            Id = FromAcc.Id,
                            NewFriend = FromAcc
                        }));
                        break;
                    }
                }
                //Cập nhật danh sách bạn của người yêu cầu kết bạn.
                ToAcc.IsOnline = IsOnline;
                foreach (UserInfo it in listUserOnline)
                {
                    if (it.Socket == socket)
                    {
                        it.DanhSachBan.Add(ToAcc);
                        break;
                    }
                }

                socket.Send(ser.Serialize(new
                {
                    Type = MessageType.ResultAddFriend,
                    Result = true,
                    Id = ToAcc.Id,
                    NewFriend = ToAcc
                }));

                //Thêm vào database.
                response = client.PostAsJsonAsync("api/Friend/" + ToAcc.Id + "/" + msg.Id, true).Result;
            }
            else
            {
                socket.Send(ser.Serialize(new
                {
                    Type = MessageType.ResultAddFriend,
                    Result = false
                }));
            }
        }

        private int TransformCellPosition(int value)
        {
            int row = value / 8;
            int col = value % 8;
            int invertRow = 7 - row;
            int invertCol = 7 - col;
            return invertRow * 8 + invertCol;
        }

        private static void XuLyDangKy(List<UserInfo> listUserOnline, IWebSocketConnection socket, JavaScriptSerializer ser, Message msg,List<Phong> listPhong)
        {
            foreach (UserInfo useritem in listUserOnline)
            {
                if (useritem.Socket == socket)
                {
                    useritem.IdTaiKhoan = msg.Id;
                    useritem.UserName = msg.UserName;
                    useritem.UserStatus = USER_STATUS.FREE;
                    //Lấy danh sách bạn bè gửi về client    
                    HttpClient client;
                    client = new HttpClient();
                    client.BaseAddress = new Uri("http://localhost:3333/");
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));

                    HttpResponseMessage response = client.GetAsync("api/Friend/" + useritem.IdTaiKhoan).Result;

                    if (response.IsSuccessStatusCode)
                    {
                        List<TaiKhoan> listFriend = (List<TaiKhoan>)response.Content.ReadAsAsync<IEnumerable<TaiKhoan>>().Result;
                        //Cập nhật tình trạng on/off line của các bạn trong danh sách.
                        foreach (TaiKhoan item in listFriend)
                        {
                            item.IsOnline = false;
                            int n = listUserOnline.Count;
                            for (int i = 0; i < n; i++)
                            {
                                if (item.Id == listUserOnline[i].IdTaiKhoan)
                                {
                                    item.IsOnline = true;
                                    break;
                                }
                            }
                        }
                        useritem.DanhSachBan = listFriend;
                    }

                    //Kết thúc code lấy danh sách bạn bè.       
                    //clone list phong and set all socket of list phong to null//test serialize
                    List<Phong> listPhongTemp = new List<Phong>();
                    for (int i = 0; i < listPhong.Count; i++)
                    {
                        Phong phong = new Phong();
                        phong.DuNguoi = listPhong[i].DuNguoi;
                        phong.IdNguoiChoiHai = listPhong[i].IdNguoiChoiHai;
                        phong.IdNguoiChoiMot = listPhong[i].IdNguoiChoiMot;
                        phong.IdPhong = listPhong[i].IdPhong;
                        phong.SoNguoi = listPhong[i].SoNguoi;
                        listPhongTemp.Add(phong);
                    }
                    useritem.Socket.Send(ser.Serialize(new
                    {
                        Type = MessageType.SendListFriend,
                        Contain = "Ban da dang ky thanh cong!",
                        ListFriend = useritem.DanhSachBan,
                        ListPhong = listPhongTemp
                    }));

                    //Cập nhật tình trạng của user này trong danh sách bạn bè.
                    foreach (UserInfo item in listUserOnline)
                    {
                        //Lấy danh sách bạn bè nếu có thì cập nhật.
                        List<TaiKhoan> dsBanBe = item.DanhSachBan;
                        foreach (TaiKhoan itembb in dsBanBe)
                        {
                            if (itembb.Id == msg.Id)
                            {
                                itembb.IsOnline = true;
                                item.Socket.Send(ser.Serialize(new
                                {
                                    Type = MessageType.Online,
                                    Id = itembb.Id
                                }));
                                break;
                            }
                        }
                    }
                    break;
                }
            }
        }

    }

    

    public class WebsocketWs
    {
        public void startWebsocket()
        {
            FleckLog.Level = LogLevel.Debug;
            var allSockets = new List<IWebSocketConnection>();
            var server = new WebSocketServer("ws://localhost:8181");
            server.Start(socket =>
            {
                socket.OnOpen = () =>
                {
                    Console.WriteLine("Open!");
                    allSockets.Add(socket);
                };
                socket.OnClose = () =>
                {
                    Console.WriteLine("Close!");
                    String from_user = ((WebSocketConnection)socket).UserName;
                    allSockets.Remove(socket);
                    string userDisconnecteddMsg = "[\"user_disconnected\", { \"name\" : \"" + from_user + "\"}]";
                    allSockets.ToList().ForEach(s => s.Send(userDisconnecteddMsg));
                };
                socket.OnMessage = message =>
                {
                    string temp = message;
                    temp = temp.Remove(0, 1);
                    temp = temp.Remove(temp.Length - 1, 1);
                    temp = "{" + temp + "}";
                    var regex = new Regex(",");
                    temp = regex.Replace(temp, ":", 1);
                    JObject jObject = JObject.Parse(temp);


                    if (jObject["user_authen"] != null)
                    {
                        JToken user_authen = jObject["user_authen"];
                        string from_User = (string)user_authen["from"];
                        ((WebSocketConnection)socket).UserName = from_User.Trim();
                        //broadcast to all user
                        string userConnectedMsg = "[\"user_connected\", { \"name\" : \"" + from_User + "\"}]";
                        //message = "[\"user_authen\",{\"from\":\"Yang\"}]"
                        allSockets.ToList().ForEach(s => s.Send(userConnectedMsg));
                        //send online user
                        string onlineUserListMsg = "[\"online_user\", [";
                        for (int i = 0; i < allSockets.Count - 1; i++)
                        {
                            onlineUserListMsg += "\"" + ((WebSocketConnection)allSockets[i]).UserName + "\" ,";
                        }
                        if (allSockets.Count > 0)
                            onlineUserListMsg += "\"" + ((WebSocketConnection)allSockets[allSockets.Count - 1]).UserName + "\"]]";
                        socket.Send(onlineUserListMsg);
                    }
                    else if (jObject["user_move"] != null)
                    {

                        JToken user_mess = jObject["user_move"];

                        string from_User = (string)user_mess["from"];
                        int fromCell = (int)user_mess["fromCell"];
                        int toCell = (int)user_mess["toCell"];

                        for (int i = 0; i < allSockets.Count; i++)
                        {
                            if (((WebSocketConnection)allSockets[i]).UserName != from_User)
                            {
                                string msg = "[\"user_move\", [ \"" + TransformCellPosition(fromCell) + "\", \"" + TransformCellPosition(toCell) + "\"]]";
                                allSockets[i].Send(msg);
                            }

                        }
                    }
                };
            });

        }

        private int TransformCellPosition(int value)
        {
            int row = value / 8;
            int col = value % 8;
            int invertRow = 7 - row;
            int invertCol = 7 - col;
            return invertRow * 8 + invertCol;
        }
    }
}